Param
(
	[string] $OWNERACCOUNT = "perth\administrator",
	[string] $OWNEREMAIL = "admin@localhost",
	[string] $OWNERPASSWORD = "P@ssword1",
	[string] $localSolutionPath = "C:\source\codeplex\spsource\SPSource\",
	[string] $SITECOLLECTIONPORT = "80",
	[string] $STAGINGSITECOLLECTIONNAME = "StagingSite",
	[string] $DEVSITECOLLECTIONNAME = "DevSite",
	[bool] $createDevSite = $false,
	[bool] $generateNewSPSourceSample = $true,
	[bool] $buildNewSPSourceSample = $true,
	[bool] $createNewStagingSite = $true
)

$STSDEVDir = "${env:ProgramFiles}\STSDev";
if ((Test-Path -path $STSDEVDir) -ne $True)
{
	throw "Please install STSDev to $STSDEVDir"
}

############################################################################
#Assumptions:
#-Running on machine with WSS/MOSS
#-C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN in path
############################################################################
$12HivesDir = "${env:CommonProgramFiles}\Microsoft Shared\web server extensions\12\"
cd $12HivesDir
[System.Reflection.Assembly]::LoadFrom("$12HivesDir\ISAPI\Microsoft.SharePoint.dll")
Set-Alias -Name stsadm -Value $env:CommonProgramFiles"\Microsoft Shared\Web Server Extensions\12\BIN\STSADM.EXE"
Set-Alias -Name wspbuilder -Value $env:ProgramFiles"\WSPTools\WSPBuilderExtensions\WSPBuilder.exe"
Set-Alias -Name stsdev -Value $env:ProgramFiles"\STSDev_v1.3\stsdev.exe"


function ExecuteCommand([string]$cmd2Execute, [bool]$checkExitCode=$false)
{
	if ($VerifyCommands) 
	{
		echo $cmd2Execute
	}
	else
	{
		invoke-expression "$cmd2Execute"
		if ( $checkExitCode -and $LastExitCode -ne 0)
		{
			Write-Host -foregroundcolor red ("Command failed: " + $cmd2Execute)
			(Read-Host "Manually fix this error and hit <ENTER> to continue")
		}
	}
	return
}

function global:Get-SPFarm{
return [Microsoft.SharePoint.Administration.SPFarm]::Local
}

function global:Get-SPWebApplication{
	Get-SPFarm |% {$_.Services} | where {'$_.TYPEName -eq "Windows SharePoint Services Web Application"'} |% {$_.WebApplications} |% {Write-Output $_}
}

#returns the SPSite at the specified URL
function get-spsite ([String]$webUrl=$(throw 'Parameter -webUrl is missing!'))
{
   return New-Object -TypeName "Microsoft.SharePoint.SPSite" -ArgumentList "$webUrl";
}

#returns the SPSite object from the specified URL
function get-spweb ([String]$webUrl=$(throw 'Parameter -webUrl is missing!'))
{
   $site =  New-Object -TypeName "Microsoft.SharePoint.SPSite" -ArgumentList "$webUrl";
   return $site.OpenWeb();
}

#returns the SPList object from the specified URL and List name
function get-splist ([String]$webUrl=$(throw 'Parameter -webUrl is missing!'),
[String]$listName=$(throw 'Parameter -listName is missing!'))
{
   $site =  New-Object -TypeName "Microsoft.SharePoint.SPSite" -ArgumentList "$webUrl";
   $web = $site.OpenWeb();
   return $web.Lists[$listName]
}

function create-spsite ([String] $url, [String] $OWNERACCOUNT, [String] $OWNEREMAIL)
{
	$uri = new-object -TypeName System.Uri -ArgumentList "$url"
	$exists = ([type]"Microsoft.SharePoint.SPSite")::Exists($uri);
	if ($exists)
	{
		"Deleting Staging SPSite"
		$site = new-object -TypeName "Microsoft.SharePoint.SPSite" -ArgumentList "$uri";
		$site.Delete();
		$site.Dispose();
	}
	$webApplication = ([type]"Microsoft.SharePoint.Administration.SPWebApplication")::Lookup($uri);
	$webApplication.Sites.Add($uri, "title", "", 1033, "STS#1",$OWNERACCOUNT, "owner", $OWNEREMAIL);
}

function get-siteurl([String] $MACHINENAME, [String] $SITECOLLECTIONPORT, [String] $SITENAME)
{
	return [string] "http://" + $MACHINENAME +":" + $SITECOLLECTIONPORT +"/sites/" + $SITENAME;
}

# Function:         new-SPWebApplication    
# Description:        Create and return a new SPWebApplication object
#             Use the default values which will create the web site at a random port
# Parameters:        none
#
function new-SPWebApplication()
{
    # Get our local SPFarm object
    $spfarm = [Microsoft.SharePoint.Administration.SPfarm]::Local

    # Use the new SPWebApplicationBuilder
    $appbuilder= new-object Microsoft.SharePoint.Administration.SPWebApplicationBuilder $spfarm

    # Create Web Application with the default settings
    
    $webapplication = $appbuilder.Create()

    # Set the timezone to Greenwich Mean Time
    $timezone=get-defaulttimezoneid
    $webapplication.DefaultTimeZone = $timezone.ID
    $webapplication.Update()

    # Actually queue the application for creation
    $webapplication.Provision()

    # return the SPWebApplication object
    $webapplication
} 

# Return the Default TimeZone as used for the majority of our sites
#
function get-defaulttimezoneid
{
    [Microsoft.SharePoint.SPregionalSettings]::Globaltimezones | where-object { $_.Description -like "*greenwich*" }
}
# Function:         set-apidentity    
# Description:        Set the credentials for the application pool for the given Web Application
# Parameters:        Url        Site Collection URL
#            UserName     UserName
#            Password     Password
function set-apidentity([string]$SiteCollectionURL, [string]$UserName, [string]$Password)
{        
    $webapp=get-spwebapplication $SiteCollectionURL
        
    $webapp.ApplicationPool.CurrentIdentityType= [Microsoft.SharePoint.Administration.IdentityType]::SpecificUser
    $webapp.ApplicationPool.UserName= $Username
    $webapp.ApplicationPool.Password= $Password
    
    # Save the settings
    $webapp.ApplicationPool.Update()

    # Roll the settings out via a Admin Job
    $webapp.ApplicationPool.Provision()
}

Clear-Host
$MACHINENAME = (get-content env:COMPUTERNAME)
$devUrl = get-siteurl $MACHINENAME $SITECOLLECTIONPORT $DEVSITECOLLECTIONNAME
$stagingUrl = get-siteurl $MACHINENAME $SITECOLLECTIONPORT $STAGINGSITECOLLECTIONNAME
$featureGuid = new-object System.Guid("259AC4AF-4CC3-4EC0-9E8D-523E9D152D7A")
$spsourceprojectlocation = $localSolutionPath + "SPSource\SPSource.csproj"
	
$GenericList_NAME = "GenericList";
$DocumentLibrary_NAME = "DocumentLibrary";
$Survey_NAME = "Survey";
$Links_NAME = "Links";
$Announcements_NAME = "Announcements";
$Contacts_NAME = "Contacts";
$Events_NAME = "Events";
$Tasks_NAME = "Tasks";
$DiscussionBoard_NAME = "DiscussionBoard";
$PictureLibrary_NAME = "PictureLibrary";
$DataSources_NAME = "DataSources";
$WebTemplateCatalog_NAME = "WebTemplateCatalog";
$UserInformation_NAME = "UserInformation";
$WebPartCatalog_NAME = "WebPartCatalog";
$ListTemplateCatalog_NAME = "ListTemplateCatalog";
$XMLForm_NAME = "XMLForm";
$MasterPageCatalog_NAME = "MasterPageCatalog";
$NoCodeWorkflows_NAME = "NoCodeWorkflows";
$WorkflowProcess_NAME = "WorkflowProcess";
$WebPageLibrary_NAME = "WebPageLibrary";
$CustomGrid_NAME = "CustomGrid";
$DataConnectionLibrary_NAME = "DataConnectionLibrary";
$WorkflowHistory_NAME = "WorkflowHistory";
$GanttTasks_NAME = "GanttTasks";
$Meetings_NAME = "Meetings";
$Agenda_NAME = "Agenda";
$MeetingUser_NAME = "MeetingUser";
$Decision_NAME = "Decision";
$MeetingObjective_NAME = "MeetingObjective";
$TextBox_NAME = "TextBox";
$ThingsToBring_NAME = "ThingsToBring";
$HomePageLibrary_NAME = "HomePageLibrary";
$Posts_NAME = "Posts";
$Comments_NAME = "Comments";
$Categories_NAME = "Categories";
$IssueTracking_NAME = "IssueTracking";
$AdminTasks_NAME = "AdminTasks";
$SURVEY_NAME = "Survey"
	
if ($createDevSite)
{
	#Build SPSource
	C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe $spsourceprojectlocation

	#TODO: create dev web app
	#$webapp = new-SPWebApplication
	#set-apIdentity $webapp.AlternateUrls[0].IncomingUrl $OWNERACCOUNT $OWNERPASSWORD

	#Create Dev Site Collection
	create-spsite $devUrl $OWNERACCOUNT $OWNEREMAIL
	$devSite = get-spsite $devUrl;
	$devWeb = $devSite.OpenWeb();

	#Create elements
	#Create Document content type and site columns
	$documentContentType = $devWeb.AvailableContentTypes["Document"];
	$contentType =  New-Object Microsoft.SharePoint.SPContentType -ArgumentList @($documentContentType, $devWeb.ContentTypes, "TestDocumentContentType");
	$devweb.ContentTypes.Add($contentType);
	$newDocumentContentType = $devweb.ContentTypes[$contentType.Id];
	$fields = $devweb.Fields;
	$fldName = $fields.Add("TestDocumentField", ([Type]"Microsoft.SharePoint.SPFieldType")::Url, $false);
	$field = $fields.GetField($fldName);
	$fieldLink = New-Object Microsoft.SharePoint.SPFieldLink -ArgumentList @($field);
	$newDocumentContentType.FieldLinks.Add($fieldLink);
	$newDocumentContentType.Update();

	$fldName = $fields.Add("TestPersonField", ([Type]"Microsoft.SharePoint.SPFieldType")::User, $false);

	#Create Item content type and site columns
	$documentContentType = $devWeb.AvailableContentTypes["Item"];
	$contentType =  New-Object Microsoft.SharePoint.SPContentType -ArgumentList @($documentContentType, $devWeb.ContentTypes, "TestItemContentType");
	$devweb.ContentTypes.Add($contentType);
	$newItemContentType = $devweb.ContentTypes[$contentType.Id];
	$fields = $devweb.Fields;
	$fldName = $fields.Add("TestItemField", ([Type]"Microsoft.SharePoint.SPFieldType")::Url, $false);
	$field = $fields.GetField($fldName);
	$fieldLink = New-Object Microsoft.SharePoint.SPFieldLink -ArgumentList @($field);
	$newItemContentType.FieldLinks.Add($fieldLink);
	$newItemContentType.Update();

	#Create Generic List
	$devWeb.Lists.Add($GenericList_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::GenericList);
	$devWeb.Lists.Add("GenericListWithExtraColumn", "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::GenericList);

	$list = $devWeb.Lists["GenericListWithExtraColumn"]
	$list.Fields.Add("TestColumn", ([Type]"Microsoft.SharePoint.SPFieldType")::Url, $false);

	$devWeb.Lists.Add("GenericListWithContentType", "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::GenericList);
	$list = $devWeb.Lists["GenericListWithContentType"]
	$list.ContentTypesEnabled = $true;
	$list.ContentTypes.Add($newItemContentType);
	$list.EnableAttachments = $false;
	$list.Update();

	$devWeb.Lists.Add($DocumentLibrary_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::DocumentLibrary);
	$devWeb.Lists.Add("DocumentLibraryWithExtraColumn", "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::DocumentLibrary);
	$list = $devWeb.Lists["DocumentLibraryWithExtraColumn"]
	$list.Fields.Add("TestColumn", ([Type]"Microsoft.SharePoint.SPFieldType")::Url, $false);

	$devWeb.Lists.Add("DocumentLibraryWithContentType", "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::DocumentLibrary);
	$list = $devWeb.Lists["DocumentLibraryWithContentType"];
	$list.ContentTypesEnabled = $true;
	$list.ContentTypes.Add($newDocumentContentType);
	$list.Update();

	$devWeb.Lists.Add($Survey_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Survey);
	$devWeb.Lists.Add($Links_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Links);
	$devWeb.Lists.Add($Announcements_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Announcements);
	$devWeb.Lists.Add($Contacts_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Contacts);
	$devWeb.Lists.Add($Events_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Events);
	$devWeb.Lists.Add($Tasks_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Tasks);
	$devWeb.Lists.Add($DiscussionBoard_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::DiscussionBoard);
	$devWeb.Lists.Add($PictureLibrary_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::PictureLibrary);
	$devWeb.Lists.Add($DataSources_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::DataSources);
	#$devWeb.Lists.Add($WebTemplateCatalog_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::WebTemplateCatalog);
	#$devWeb.Lists.Add($UserInformation_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::UserInformation);
	#$devWeb.Lists.Add($WebPartCatalog_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::WebPartCatalog);
	#$devWeb.Lists.Add($ListTemplateCatalog_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::ListTemplateCatalog);
	$devWeb.Lists.Add($XMLForm_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::XMLForm);
	#$devWeb.Lists.Add($MasterPageCatalog_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::MasterPageCatalog);
	$devWeb.Lists.Add($NoCodeWorkflows_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::NoCodeWorkflows);
	$devWeb.Lists.Add($WorkflowProcess_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::WorkflowProcess);
	$devWeb.Lists.Add($WebPageLibrary_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::WebPageLibrary);
	$devWeb.Lists.Add($CustomGrid_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::CustomGrid);
	$devWeb.Lists.Add($DataConnectionLibrary_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::DataConnectionLibrary);
	$devWeb.Lists.Add($WorkflowHistory_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::WorkflowHistory);
	$devWeb.Lists.Add($GanttTasks_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::GanttTasks);
	#"Invalid list template."$devWeb.Lists.Add($Meetings_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Meetings);
	#"Invalid list template."$devWeb.Lists.Add($Agenda_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Agenda);
	#"Invalid list template."$devWeb.Lists.Add($MeetingUser_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::MeetingUser);
	#"Invalid list template."$devWeb.Lists.Add($Decision_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Decision);
	#"Invalid list template."$devWeb.Lists.Add($MeetingObjective_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::MeetingObjective);
	#"Invalid list template."$devWeb.Lists.Add($TextBox_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::TextBox);
	#"Invalid list template."$devWeb.Lists.Add($ThingsToBring_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::ThingsToBring);
	#"Invalid list template."$devWeb.Lists.Add($HomePageLibrary_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::HomePageLibrary);
	#"Invalid list template."$devWeb.Lists.Add($Posts_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Posts);
	#"Invalid list template."$devWeb.Lists.Add($Comments_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Comments);
	#"Invalid list template."$devWeb.Lists.Add($Categories_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::Categories);
	#"Invalid list template."$devWeb.Lists.Add($IssueTracking_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::IssueTracking);
	#"Invalid list template."$devWeb.Lists.Add($AdminTasks_NAME, "", ([Type]"Microsoft.SharePoint.SPListTemplateType")::AdminTasks);

	$devSite.Dispose();
	$devWeb.Dispose();
}

if ($generateNewSPSourceSample)
{
	#Run SPSource to create new reverse engineered files
	$sampleprojectfolder = $localSolutionPath + "SPSourceSample\"
	cd $sampleprojectfolder
	ExecuteCommand "& $localSolutionPath\SPSource\obj\Debug\SPSource.exe -d $devUrl" $true
}

if ($buildNewSPSourceSample)
{
	#Build project to create WSP to wrap up new reverse engineered files
	$SPSourceSampleSolutionFile = $localSolutionPath + "SPSourceSample\SPSourceSample.sln"
	C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe $SPSourceSampleSolutionFile
	#stsdev /refresh  "SPSourceSample" "C:\sandbox\codeplex\SPSource\SPSourceSample\"

	#TODO: replace STSDEV with WSPBuilder
	#$SPSourceSampleSolutionDir = $localSolutionPath + "SPSourceSample";
	#$SPSourceSampleProjectFile = $SPSourceSampleSolutionDir + "\SPSourceSample.proj";
	#wspbuilder -ProjectPath $SPSourceSampleProjectFile -SolutionPath $SPSourceSampleSolutionDir -Outputpath $psconfig -cmd configdb -create -server ""$LocalDBServer"" localSolutionPath -BuildSolution True
}

if ($createNewStagingSite)
{
	#Create Staging Site Collection
	$stagingUrl
	create-spsite  $stagingUrl $OWNERACCOUNT $OWNEREMAIL
	$stagingSite = get-spsite $stagingUrl;

	$sampleprojectdeploymentfolder = $localSolutionPath + "SPSourceSample\DeploymentFiles\";
	#Deploy WSP to Staging Site Collection
	cd $sampleprojectdeploymentfolder
	stsadm -o retractsolution -name SPSourceSample.wsp -immediate 
	stsadm -o execadmsvcjobs
	stsadm -o deletesolution -name SPSourceSample.wsp
	stsadm -o execadmsvcjobs
	stsadm -o addsolution -filename SPSourceSample.wsp
	stsadm -o execadmsvcjobs
	stsadm -o deploysolution -name SPSourceSample.wsp -immediate -allowgacdeployment
	stsadm -o execadmsvcjobs
	stsadm -o activatefeature -name SPSourceSample -url $stagingUrl

	$stagingWeb = $stagingSite.OpenWeb();

	#Create elements
	#Create Generic List
	$genericList = $stagingWeb.Lists[$GENERICLIST_NAME];
	$item = $genericList.Items.Add();
	$item["Title"] = "New List Item Title";
	$item.Update();

	$stagingWeb.Dispose();
	#Run Tests
	##########TODO########################


	#Run Web Tests
	##########TODO########################
	$ie = new-object -comobject "InternetExplorer.Application"
	$ie.visible = $true
	$ie.navigate($stagingUrl)
}